package utils

import (
	"context"
	"errors"
	"time"

	"github.com/jinzhu/copier"
)

func StructDeepCopy(ctx context.Context, to, form any) error {
	if err := copier.CopyWithOption(to, form, copier.Option{IgnoreEmpty: true, DeepCopy: true, Converters: copierDefConverter()}); err != nil {
		return err
	}
	return nil
}

func StructCopy(ctx context.Context, to, from any) error {
	if err := copier.CopyWithOption(to, from, copier.Option{IgnoreEmpty: true, DeepCopy: false, Converters: copierDefConverter()}); err != nil {
		return err
	}
	return nil
}

// ArrayCopy 数组拷贝
// to: 目标类型值对象
func ArrayCopy[T any, S any](ctx context.Context, to T, from []S) (rt []T, err error) {
	if 0 == len(from) {
		return make([]T, 0), err
	}
	rt = make([]T, 0, len(from))
	for _, a := range from {
		var t T
		if err = StructDeepCopy(ctx, &t, &a); err != nil {
			return
		}
		rt = append(rt, t)
	}
	return
}

// copierDefConverter 自定义类型转换器
func copierDefConverter() []copier.TypeConverter {
	return []copier.TypeConverter{
		{
			SrcType: time.Time{},
			DstType: int64(0),
			Fn: func(src interface{}) (interface{}, error) {
				s, ok := src.(time.Time)
				if !ok {
					return nil, errors.New("src type :time.Time not matching")
				}
				return s.UnixMilli(), nil
			},
		},
		{
			SrcType: int64(0),
			DstType: time.Time{},
			Fn: func(src interface{}) (interface{}, error) {
				s, ok := src.(int64)
				if !ok {
					return nil, errors.New("src type :time.Time not matching")
				}
				return time.UnixMilli(s), nil
			},
		},
	}
}
